package cn.csg.ams.collect2.poptopics.datahub;


import cn.csg.ams.collect2.poptopics.entity.OutageJudgeData;
import cn.csg.ams.collect2.poptopics.entity.OutageJudgeVO;
import cn.csg.ams.collect2.poptopics.redisPool.AlarmPool;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 * 停复电研判
 */
@Component
public class OutageJudge {

    private static Logger logger = LoggerFactory.getLogger(OutageJudge.class);


    /**
     * 停电存在的告警数量进行研判
     *
     * @param outageJudgeVO
     * @return
     */
    public List<OutageJudgeData> outageJudge(OutageJudgeVO outageJudgeVO) {
        setOutageJudgeVO(outageJudgeVO);
        /**
         * 台区停电研判
         */
        OutageJudgeData outageJudgeData = taOutageJudge(outageJudgeVO);
        if (outageJudgeData.isStats()) {
            return Arrays.asList(outageJudgeData);
        }

        /**
         * 分路停电研判
         */
        // List<OutageJudgeData> shuntOutageJudge = shuntOutageJudge(outageJudgeVO);

        /**
         * 部分用户停电
         */
        OutageJudgeData meterOutageJudge = meterOutageJudge(outageJudgeVO);
        if (meterOutageJudge.isStats()) {
            return Arrays.asList(meterOutageJudge);
        }

        // List<OutageJudgeData> outageJudgeList = new ArrayList<>();
        // outageJudgeList.addAll(shuntOutageJudge);
        // outageJudgeList.add(meterOutageJudge);
        return Arrays.asList(OutageJudgeData.fail());
    }

    public void setOutageJudgeVO(OutageJudgeVO outageJudgeVO) {
        List<AlarmPool.AlarmInfo> alarmList = outageJudgeVO.getAlarmList();
        // 配变终端数量
        int pbTermCount = 0;
        // 负荷终端数量
        int fhTermCount = 0;
        // 集中器数量
        int jzqTermCount = 0;
        // 分路数量
        int branchCount = 0;
        // 电表告警数量
        int dbCount = 0;

        Set<String> branchList = new TreeSet<>();
        Map<String, Integer> branchMap = new HashMap<>();
        Map<String, Set<String>> branchMeterList = new HashMap<>();
        for (AlarmPool.AlarmInfo alarmInfo : alarmList) {
            // 电表告警
            if ("2".equals(alarmInfo.getAlarmSourCode())) {
                branchMap.put(alarmInfo.getShuntNo(), alarmInfo.getShuntCustCnt());
                if ("2".equals(alarmInfo.getOutageType())) {
                    branchList.add(alarmInfo.getShuntNo());
                    branchCount++;
                    continue;
                }
                if (branchMeterList.containsKey(alarmInfo.getShuntNo())) {
                    Set<String> meterList = branchMeterList.get(alarmInfo.getShuntNo());
                    meterList.add(alarmInfo.getRunMeterId());
                } else {
                    Set<String> meterList = new TreeSet<>();
                    meterList.add(alarmInfo.getRunMeterId());
                    branchMeterList.put(alarmInfo.getShuntNo(), meterList);
                }
                dbCount++;
                continue;
            }

            // 终端告警
            if ("04".equals(alarmInfo.getTermType()) || "26".equals(alarmInfo.getTermType())) {
                // 配变终端
                pbTermCount++;
                continue;
            }
            if ("05".equals(alarmInfo.getTermType())) {
                // 配变终端
                jzqTermCount++;
                continue;
            }
            if ("03".equals(alarmInfo.getTermType())) {
                // 负控终端
                fhTermCount++;
                continue;
            }
        }

        outageJudgeVO.setPbTermCount(pbTermCount);
        outageJudgeVO.setFhTermCount(fhTermCount);
        outageJudgeVO.setJzqTermCount(jzqTermCount);
        outageJudgeVO.setBranchCount(branchCount);
        outageJudgeVO.setDbCount(dbCount);
        outageJudgeVO.setBranchList(branchList);
        outageJudgeVO.setBranchMeterList(branchMeterList);
        outageJudgeVO.setBranchMap(branchMap);
    }

    /**
     * 台区是否复电判断
     *
     * @param outageJudgeVO
     * @return
     */
    public boolean taOutageRestoreJudge(OutageJudgeVO outageJudgeVO) {
        setOutageJudgeVO(outageJudgeVO);
        // 配变终端数量
        int pbTermCount = outageJudgeVO.getPbTermCount();
        // 负荷终端
        int fhTermCount = outageJudgeVO.getFhTermCount();
        // 集中器数量
        int jzqTermCount = outageJudgeVO.getJzqTermCount();
        // 分路数量
        int branchCount = outageJudgeVO.getBranchCount();
        // 电表告警数量
        int dbCount = outageJudgeVO.getDbCount();

        String taType = outageJudgeVO.getTaType();

        // 台区判断如果为负控终端 直接输出台区停电
        if (pbTermCount + fhTermCount + jzqTermCount > 0 && !"01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-0");
            return false;
        }

        // 3分钟内收到同台区配变终端与集中器告警，输出台区停电，满足规则ZDGZ1-1
        if (pbTermCount + fhTermCount > 0 && jzqTermCount > 0 && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-1");
            return false;
        }

        // 3分钟内收到同台区配变终端与3个以上低压用户告警，输出台区停电，满足规则ZDGZ1-2
        int baseCount = outageJudgeVO.getLowCustCnt() < 3 ? 1 : 3;
        if (pbTermCount > 0 && dbCount >= baseCount && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-2");
            return false;
        }

        // 3分钟内收到同台区集中器告警与3个以上同集中器低压用户告警，输出台区停电，满足规则ZDGZ1-3
        if (jzqTermCount > 0 && dbCount >= baseCount && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-3");
            return false;
        }

        // 配变终端告警  +  分支告警
        if (pbTermCount > 0 && branchCount > 0 && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-4");
            return false;
        }

        // 同台半数以上人停电 视为台区停电 规则DBGJ1-8
        int lowCustCnt = outageJudgeVO.getLowCustCnt();
        if (dbCount > lowCustCnt * 0.3 && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-7");
            return false;
        }
        return true;
    }

    /**
     * 分支是否复电判断
     *
     * @param outageJudgeVO
     * @return
     */
    public boolean shuntOutageRestoreJudge(OutageJudgeVO outageJudgeVO) {
        setOutageJudgeVO(outageJudgeVO);

        String shuntNo = outageJudgeVO.getShuntNo();

        if (StrUtil.isBlank(shuntNo)) {
            return false;
        }

        Map<String, Set<String>> branchMeterList = outageJudgeVO.getBranchMeterList();
        Map<String, Integer> branchMap = outageJudgeVO.getBranchMap();
        String taType = outageJudgeVO.getTaType();
        Set<String> meterList = branchMeterList.get(shuntNo);
        if (CollUtil.isEmpty(meterList)) {
            return true;
        }
        int baseCount = branchMap.get(shuntNo) < 3 ? 1 : 3;
        // 收到同一个分支线路告警 和分支线路下三个低压用户停电，输出分支停电，满足规则ZDGZ1-9
        if (meterList.size() >= baseCount && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-5");
            return false;
        }
        int branchCustCnt = branchMap.get(shuntNo);
        // 一半以上分路用户停电 视为分路停电 规则DBGJ1-10
        if (meterList.size() > branchCustCnt * 0.3 && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-8");
            return false;
        }
        return true;
    }

    /**
     * 部分用户是否复电
     *
     * @param outageJudgeVO
     * @return
     */
    public boolean meterOutageRestoreJudge(OutageJudgeVO outageJudgeVO) {
        setOutageJudgeVO(outageJudgeVO);
        Map<String, Set<String>> branchMeterList = outageJudgeVO.getBranchMeterList();
        List<String> judgeMeter = new ArrayList<>();
        for (Map.Entry<String, Set<String>> entry : branchMeterList.entrySet()) {
            judgeMeter.addAll(new ArrayList<>(entry.getValue()));
        }
        int dbCount = judgeMeter.size();
        // 3分钟内3个及以上用户停电，输出部分用户停电
        if (dbCount >= 3) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-6, 部分用户停电");
            return false;
        }
        return true;
    }

    /**
     * 台区停电研判
     *
     * @param outageJudgeVO
     * @return
     */
    private OutageJudgeData taOutageJudge(OutageJudgeVO outageJudgeVO) {
        // 配变终端数量
        int pbTermCount = outageJudgeVO.getPbTermCount();
        // 负荷终端
        int fhTermCount = outageJudgeVO.getFhTermCount();
        // 集中器数量
        int jzqTermCount = outageJudgeVO.getJzqTermCount();
        // 分路数量
        int branchCount = outageJudgeVO.getBranchCount();
        // 电表告警数量
        int dbCount = outageJudgeVO.getDbCount();

        String taType = outageJudgeVO.getTaType();

        // 台区判断如果为负控终端 直接输出台区停电
        if (pbTermCount + fhTermCount + jzqTermCount > 0 && !"01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-0");
            OutageJudgeData outageJudgeData = OutageJudgeData.OK("ZDGZ1-0", "1");
            outageJudgeData.setJudgeTa(outageJudgeVO.getTaNo());
            return outageJudgeData;
        }

        // 3分钟内收到同台区配变终端与集中器告警，输出台区停电，满足规则ZDGZ1-1
        if (pbTermCount + fhTermCount > 0 && jzqTermCount > 0 && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-1");
            OutageJudgeData outageJudgeData = OutageJudgeData.OK("ZDGZ1-1", "1");
            outageJudgeData.setJudgeTa(outageJudgeVO.getTaNo());
            return outageJudgeData;
        }

        // 3分钟内收到同台区配变终端与3个以上低压用户告警，输出台区停电，满足规则ZDGZ1-2
        int baseCount = outageJudgeVO.getLowCustCnt() < 3 ? 1 : 3;
        if (pbTermCount > 0 && dbCount >= baseCount && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-2");
            OutageJudgeData outageJudgeData = OutageJudgeData.OK("ZDGZ1-2", "1");
            outageJudgeData.setJudgeTa(outageJudgeVO.getTaNo());
            return outageJudgeData;
        }

        // 3分钟内收到同台区集中器告警与3个以上同集中器低压用户告警，输出台区停电，满足规则ZDGZ1-3
        if (jzqTermCount > 0 && dbCount >= baseCount && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-3");
            OutageJudgeData outageJudgeData = OutageJudgeData.OK("ZDGZ1-3", "1");
            outageJudgeData.setJudgeTa(outageJudgeVO.getTaNo());
            return outageJudgeData;
        }

        // 配变终端告警  +  分支告警
        if (pbTermCount > 0 && branchCount > 0 && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-4");
            OutageJudgeData outageJudgeData = OutageJudgeData.OK("ZDGZ1-4", "1");
            outageJudgeData.setJudgeTa(outageJudgeVO.getTaNo());
            return outageJudgeData;
        }

        // 同台半数以上人停电 视为台区停电 规则DBGJ1-8
        int lowCustCnt = outageJudgeVO.getLowCustCnt();
        if (dbCount > lowCustCnt * 0.6 && "01".equals(taType)) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-7");
            OutageJudgeData outageJudgeData = OutageJudgeData.OK("ZDGZ1-7", "1");
            outageJudgeData.setJudgeTa(outageJudgeVO.getTaNo());
            return outageJudgeData;
        }
        return OutageJudgeData.fail();
    }

    /**
     * 分路停电研判
     *
     * @param outageJudgeVO
     * @return
     */
    private List<OutageJudgeData> shuntOutageJudge(OutageJudgeVO outageJudgeVO) {

        Map<String, Set<String>> branchMeterList = outageJudgeVO.getBranchMeterList();

        Map<String, Integer> branchMap = outageJudgeVO.getBranchMap();

        Set<String> branchList = outageJudgeVO.getBranchList();
        String taType = outageJudgeVO.getTaType();
        List<OutageJudgeData> outageJudgeDataList = new ArrayList<>();

        for (String branchNo : branchList) {
            Set<String> meterList = branchMeterList.get(branchNo);
            if (CollUtil.isEmpty(meterList)) {
                continue;
            }
            int baseCount = branchMap.get(branchNo) < 3 ? 1 : 3;
            // 收到同一个分支线路告警 和分支线路下三个低压用户停电，输出分支停电，满足规则ZDGZ1-9
            if (meterList.size() >= baseCount && "01".equals(taType)) {
                logger.info("==============> 研判结果，满足规则ZDGZ1-5");
                OutageJudgeData outageJudgeData = OutageJudgeData.OK("ZDGZ1-5", "2");
                outageJudgeData.setJudgeShunt(outageJudgeVO.getTaNo());
                outageJudgeDataList.add(outageJudgeData);
                branchMeterList.remove(branchNo);
            }
        }

        for (Map.Entry<String, Set<String>> branchMeter : branchMeterList.entrySet()) {
            Set<String> meterList = branchMeter.getValue();
            String branchNo = branchMeter.getKey();
            int branchCustCnt = branchMap.get(branchNo);
            // 一半以上分路用户停电 视为分路停电 规则DBGJ1-10
            if (meterList.size() > branchCustCnt * 0.6 && "01".equals(taType)) {
                logger.info("==============> 研判结果，满足规则ZDGZ1-8");
                OutageJudgeData outageJudgeData = OutageJudgeData.OK("ZDGZ1-8", "2");
                outageJudgeData.setJudgeShunt(outageJudgeVO.getTaNo());
                outageJudgeDataList.add(outageJudgeData);
                branchMeterList.remove(branchNo);
            }
        }
        return outageJudgeDataList;
    }

    /**
     * 部分用户停电
     *
     * @param outageJudgeVO
     * @return
     */
    private OutageJudgeData meterOutageJudge(OutageJudgeVO outageJudgeVO) {
        Map<String, Set<String>> branchMeterList = outageJudgeVO.getBranchMeterList();
        List<String> judgeMeter = new ArrayList<>();
        for (Map.Entry<String, Set<String>> entry : branchMeterList.entrySet()) {
            judgeMeter.addAll(new ArrayList<>(entry.getValue()));
        }
        int dbCount = judgeMeter.size();
        // 3分钟内3个及以上用户停电，输出部分用户停电
        if (dbCount >= 3) {
            logger.info("==============> 研判结果，满足规则ZDGZ1-6, 部分用户停电");
            OutageJudgeData outageJudgeData = OutageJudgeData.OK("ZDGZ1-6", "0");
            outageJudgeData.setJudgeMeter(judgeMeter);
            outageJudgeData.setJudgeTa(outageJudgeVO.getTaNo());
            return outageJudgeData;
        }
        return OutageJudgeData.fail();
    }

}
